package com.autonavi.abs.common.util;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonSyntaxException;

import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author wwy
 * @version V1.0
 * <p>Description: json utils</p>
 * @date 2020-07-23 12:22
 */
public class JsonUtils {

    public static String getJsonUTCDateFormat(Object object) {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(Date.class, new UTCFormatDateTimeSerializer());
        String result = gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create().toJson(object);
        return result;
    }

    public static String getJsonUTCDateFormatLowerCase(Object object) {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(Date.class, new UTCFormatDateTimeSerializer());
        String result = gsonBuilder.create().toJson(object);
        return result;
    }

    public static String getJsonUTCDateFormatOfExpose(Object object) {
        GsonBuilder gsonBuilder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();
        gsonBuilder.registerTypeAdapter(Date.class, new UTCFormatDateTimeSerializer());
        String result = gsonBuilder.create().toJson(object);
        return result;
    }

    public static <T> T fromJsonUTCDateFormat(String json, Class<T> classOfT) throws JsonSyntaxException {
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(Date.class, new UTCFormatDateTimeSerializer());
        return gsonBuilder.create().fromJson(json, classOfT);
    }

    public static String getJson(Object object) {
        String result = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(object);
        return result;
    }

    public static String getJsonShortDate(Object object) {
        String result = new GsonBuilder().setDateFormat("yyyy-MM-dd").create().toJson(object);
        return result;
    }

    public static <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
        return new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().fromJson(json, classOfT);
    }

    public static <T> T fromJsonWithDateFormat(String json, Class<T> classOfT, String dateFormat) throws JsonSyntaxException {
        return new GsonBuilder().setDateFormat(dateFormat).create().fromJson(json, classOfT);
    }

    public static <T> T fromJson(String json, Type classOfT) throws JsonSyntaxException {
        return new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create().fromJson(json, classOfT);
    }

    public static <T> T fromJsonWithDateFormat(String json, Type classOfT, String dateFormat) throws JsonSyntaxException {
        return new GsonBuilder().setDateFormat(dateFormat).create().fromJson(json, classOfT);
    }

    public static class NormalStringSerializer implements JsonSerializer<String>, JsonDeserializer<String> {
        public JsonElement serialize(final String src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }

        @Override
        public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            return json.getAsString();
        }
    }

    public static class UTCFormatDateTimeSerializer implements JsonSerializer<Date>, JsonDeserializer<Date> {
        @Override
        public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(DateTimeUtils.getUTC8Str(src));
        }

        @Override
        public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            return DateTimeUtils.parseDate(json.getAsJsonPrimitive().getAsString(), "yyyy-MM-dd'T'HH:mm:ss.SSS+08:00");
        }
    }

    public static String getJson(Object object, final String... includeFields) {
        ExclusionStrategy myExclusionStrategy = new ExclusionStrategy() {
            @Override
            public boolean shouldSkipField(FieldAttributes fa) {
                List<String> includes = Arrays.asList(includeFields);
                return !includes.contains(fa.getName());
            }

            @Override
            public boolean shouldSkipClass(Class<?> clazz) {
                return false;
            }
        };
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.disableHtmlEscaping();
        return gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss").setExclusionStrategies(myExclusionStrategy).create().toJson(object);
    }

}
